/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/java-pdf-library-support/
 *
 * (C) Copyright 1997-2013, IDRsolutions and Contributors.
 *
 * 	This file is part of JPedal
 *
     This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 *
 * ---------------
 * PrintPanel.java
 * ---------------
 */
package org.jpedal.examples.viewer.gui.popups;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.text.NumberFormat;
import java.util.ArrayList;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.ResolutionSyntax;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.standard.PageRanges;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jpedal.Display;
import org.jpedal.PdfDecoder;
import org.jpedal.examples.viewer.Viewer;
import org.jpedal.examples.viewer.paper.MarginPaper;
import org.jpedal.examples.viewer.paper.PaperSizes;
import org.jpedal.exception.PdfException;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.objects.PrinterOptions;
import org.jpedal.utils.Messages;

public class PrintPanel extends javax.swing.JPanel {

	private static final long serialVersionUID = -6093216971364470153L;

	private boolean debugPrinterChange = false;

	int pageCount, currentPage, currentPreviewedPage = 1, pagePrintCount = 1;
	private boolean okClicked = false;

	private String[] printersList;

	private PaperSizes paperDefinitions;

	private int defaultResolution;

	private boolean isFirstTime = true;

	private final static double mmPerSubInch = 25.4 / 72;

	private PdfDecoder pdf;

	public PrintPanel(String[] printersList, String defaultPrinter, PaperSizes paperDefinitions, int defaultResolution, int pageNumber,
			PdfDecoder decoder) {

		this.pdf = decoder;
		this.pageCount = this.pdf.getPageCount();
		this.currentPage = pageNumber;

		this.defaultResolution = defaultResolution;

		this.paperDefinitions = paperDefinitions;

		resetDefaults(printersList, defaultPrinter, this.pageCount, this.currentPage);

		this.isFirstTime = false;
	}

	public void resetDefaults(String[] printersList, String defaultPrinter, int pageCount, int currentPage) {

		// this.defaultPrinter=defaultPrinter;
		this.printersList = printersList;
		this.pageCount = pageCount;
		this.currentPage = currentPage;

		initComponents();

		if (this.pageSize.getItemCount() == 0) return;

		int defaultPagesize = this.paperDefinitions.getDefaultPageIndex();
		if (defaultPagesize < this.pageSize.getModel().getSize()) this.pageSize.setSelectedIndex(defaultPagesize);

		/** set selected printer */
		String printerFlag = System.getProperty("org.jpedal.defaultPrinter");
		if (printerFlag != null) {
			for (String aPrintersList : printersList) {
				if (printerFlag.equals(aPrintersList)) {
					this.printerName.setSelectedItem(aPrintersList);
				}
			}
		}
		else {
			this.printerName.setSelectedItem(defaultPrinter);
		}
	}

	/**
	 * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */

	// <editor-fold defaultstate="collapsed" desc=" Generated Code ">
	private void initComponents() {

		if (this.isFirstTime) {
			this.buttonGroup1 = new javax.swing.ButtonGroup();
			this.printerPanel = new javax.swing.JPanel();
			this.jLabel1 = new javax.swing.JLabel();
			this.jLabel2 = new javax.swing.JLabel();
			this.tabbedPane = new javax.swing.JTabbedPane();
			this.printerName = new javax.swing.JComboBox();
			this.pageSize = new javax.swing.JComboBox();
			this.jLabel10 = new JLabel();
			this.jLabel11 = new javax.swing.JLabel();
			this.jLabel12 = new javax.swing.JLabel();
			this.jLabel13 = new javax.swing.JLabel();
			this.jLabel14 = new javax.swing.JLabel();
			this.jLabel15 = new javax.swing.JLabel();
			this.left = new javax.swing.JSpinner();
			this.right = new javax.swing.JSpinner();
			this.top = new javax.swing.JSpinner();
			this.bottom = new javax.swing.JSpinner();
			this.resolution = new javax.swing.JComboBox();
			this.printRangePanel = new javax.swing.JPanel();
			this.pagesFrom = new javax.swing.JTextField();
			this.printRangeCurrentPage = new javax.swing.JRadioButton();
			this.printRangeAll = new javax.swing.JRadioButton();
			this.printRangeCurrentView = new javax.swing.JRadioButton();
			this.printRangeFrom = new javax.swing.JRadioButton();
			this.jLabel4 = new javax.swing.JLabel();
			this.printRangeSubset = new javax.swing.JComboBox();
			this.printRangeReversePages = new javax.swing.JCheckBox();
			this.jLabel7 = new javax.swing.JLabel();
			this.pagesTo = new javax.swing.JTextField();
			this.pageHandlingPanel = new javax.swing.JPanel();
			this.previewPanel = new javax.swing.JPanel();
			this.previewComponent = new javax.swing.JComponent() {

				private static final long serialVersionUID = -2687893784898612593L;

				@Override
				public void paintComponent(Graphics g) {
					printPreview((Graphics2D) g);
				}
			};
			this.previewSlider = new CustomSlider();
			this.jLabel8 = new javax.swing.JLabel();
			this.printHandlingCopies = new javax.swing.JSpinner();
			this.jLabel9 = new javax.swing.JLabel();
			this.printHandlingScaling = new javax.swing.JComboBox();
			this.autoRotateCenter = new javax.swing.JCheckBox();
			this.paperSourceByPDF = new javax.swing.JCheckBox();
			this.grayscale = new javax.swing.JCheckBox();
			// printToFile = new javax.swing.JCheckBox();
			this.okButton = new javax.swing.JButton();

			this.cancelButton = new javax.swing.JButton();

		}
		else this.removeAll();

		setLayout(null);

		add(this.tabbedPane);
		this.tabbedPane.setBounds(10, 7, 400, 330);

		/**
		 * START Printer PANEL
		 */
		this.printerPanel.setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();

		// printerPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null,
		// Messages.getMessage("PdfViewerLabel.Printer"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
		// javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 11), new java.awt.Color(0, 0, 255)));

		this.jLabel1.setText(Messages.getMessage("PdfViewerPrint.Name"));
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.insets = new Insets(5, 5, 5, 5);
		this.printerPanel.add(this.jLabel1, gbc);
		// jLabel1.setBounds(10, 20, 60, 14);

		this.jLabel2.setText(Messages.getMessage("PdfViewerPrint.PageSize"));
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel2, gbc);
		// jLabel2.setBounds(10, 52, 70, 14);

		this.printerName.setModel(new javax.swing.DefaultComboBoxModel(this.printersList));
		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.gridwidth = 5;
		this.printerPanel.add(this.printerName, gbc);
		// printerName.setBounds(90, 20, 290, 22);
		this.printerName.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (PrintPanel.this.debugPrinterChange) System.out.println("itemStateChanged");
				PrintPanel.this.previewComponent.repaint();
				if (PrintPanel.this.debugPrinterChange) System.out.println("repainted preview component");
				PrintPanel.this.okButton.setEnabled(false);
				PrintPanel.this.pageSize.setEnabled(false);
				PrintPanel.this.pageSize.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Loading..." }));
				PrintPanel.this.resolution.setEnabled(false);
				PrintPanel.this.resolution.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Loading..." }));
				if (PrintPanel.this.debugPrinterChange) System.out.println("GUI options disabled");
				Thread t = new Thread() {
					@Override
					public void run() {
						if (PrintPanel.this.debugPrinterChange) System.out.println("Thread invoked.");
						PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
						if (PrintPanel.this.debugPrinterChange) System.out.println("Found print services.");
						PrintService p = null;
						for (PrintService p1 : ps) {
							if (PrintPanel.this.debugPrinterChange) System.out.println("checking " + p1.getName());
							if (p1.getName().equals(PrintPanel.this.printerName.getSelectedItem())) {
								p = p1;
								if (PrintPanel.this.debugPrinterChange) System.out.println("Match!");
							}
						}

						if (p != null) {
							if (PrintPanel.this.debugPrinterChange) System.out.println("Getting available resolutions...");
							PrintPanel.this.resolution.setModel(new javax.swing.DefaultComboBoxModel(getAvailableResolutions(p)));
							if (PrintPanel.this.debugPrinterChange) System.out.println("Getting default resolution...");
							int resInd = getDefaultResolutionIndex();
							if (PrintPanel.this.resolution.getModel().getSize() > resInd) PrintPanel.this.resolution.setSelectedIndex(resInd);
							PrintPanel.this.resolution.setEnabled(true);
							PrintPanel.this.paperDefinitions.setPrintService(p);
							if (PrintPanel.this.debugPrinterChange) System.out.println("Getting available paper sizes...");
							PrintPanel.this.pageSize.setModel(new javax.swing.DefaultComboBoxModel(getAvailablePaperSizes()));
							if (PrintPanel.this.debugPrinterChange) System.out.println("Getting default pagesize...");
							int pageInd = PrintPanel.this.paperDefinitions.getDefaultPageIndex();
							if (PrintPanel.this.pageSize.getModel().getSize() > pageInd) PrintPanel.this.pageSize.setSelectedIndex(pageInd);
							PrintPanel.this.pageSize.setEnabled(true);
							PrintPanel.this.okButton.setEnabled(true);
							if (PrintPanel.this.debugPrinterChange) System.out.println("Reenabled GUI");
						}

						if (PrintPanel.this.debugPrinterChange) System.out.println("Updating margins");
						updateMargins();

					}
				};
				if (PrintPanel.this.debugPrinterChange) System.out.println("Invoking update thread...");
				SwingUtilities.invokeLater(t);
			}
		});
		Thread t = new Thread() {

			@Override
			public void run() {
				PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
				PrintService p = null;
				for (PrintService p1 : ps) {
					if (p1.getName().equals(PrintPanel.this.printerName.getSelectedItem())) p = p1;
				}

				if (p != null) {
					PrintPanel.this.paperDefinitions.setPrintService(p);
					PrintPanel.this.resolution.setModel(new javax.swing.DefaultComboBoxModel(getAvailableResolutions(p)));
					int defaultResolution = getDefaultResolutionIndex();
					if (PrintPanel.this.resolution.getModel().getSize() > defaultResolution) PrintPanel.this.resolution
							.setSelectedIndex(defaultResolution);
					PrintPanel.this.resolution.setEnabled(true);
					PrintPanel.this.pageSize.setModel(new javax.swing.DefaultComboBoxModel(getAvailablePaperSizes()));
					int defaultPageSize = PrintPanel.this.paperDefinitions.getDefaultPageIndex();
					if (defaultPageSize < PrintPanel.this.pageSize.getModel().getSize()) PrintPanel.this.pageSize.setSelectedIndex(defaultPageSize);
					PrintPanel.this.pageSize.setEnabled(true);
					PrintPanel.this.okButton.setEnabled(true);
				}

				updateMargins();
			}
		};
		this.pageSize.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Loading..." }));
		this.pageSize.setEnabled(false);
		this.resolution.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Loading..." }));
		this.resolution.setEnabled(false);
		this.okButton.setEnabled(false);
		t.start();

		this.pageSize.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
				updateMargins();
			}
		});

		gbc.gridx = 1;
		gbc.gridy = 1;
		gbc.gridwidth = 5;
		this.printerPanel.add(this.pageSize, gbc);
		// pageSize.setBounds(90, 49, 290, 22);

		this.jLabel10.setText(Messages.getMessage("PdfViewerPrintMargins.margin"));
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel10, gbc);
		// jLabel10.setBounds(10, 85, 150, 22);

		this.jLabel11.setText(Messages.getMessage("PdfViewerPrintMargins.left"));
		gbc.gridx = 1;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel11, gbc);
		// jLabel11.setBounds(105,85,100,22);

		this.left.setModel(new CustomSpinnerModel());
		// left.setBounds(140,85,65,22);
		gbc.gridx = 2;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.left.setMinimumSize(new Dimension(65, 22));
		this.left.setPreferredSize(new Dimension(65, 22));
		this.printerPanel.add(this.left, gbc);

		this.jLabel12.setText(Messages.getMessage("PdfViewerPrintMargins.right"));
		gbc.gridx = 3;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel12, gbc);
		// jLabel12.setBounds(255,85,100,22);

		this.right.setModel(new CustomSpinnerModel());
		// right.setBounds(300,85,65,22);
		gbc.gridx = 4;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.right.setMinimumSize(new Dimension(65, 22));
		this.right.setPreferredSize(new Dimension(65, 22));
		this.printerPanel.add(this.right, gbc);

		this.jLabel13.setText(Messages.getMessage("PdfViewerPrintMargins.top"));
		gbc.gridx = 1;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel13, gbc);
		// jLabel13.setBounds(105,116,100,22);

		this.top.setModel(new CustomSpinnerModel());
		// top.setBounds(140,116,65,22);
		gbc.gridx = 2;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.top.setMinimumSize(new Dimension(65, 22));
		this.top.setPreferredSize(new Dimension(65, 22));
		this.printerPanel.add(this.top, gbc);

		this.jLabel14.setText(Messages.getMessage("PdfViewerPrintMargins.bottom"));
		gbc.gridx = 3;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel14, gbc);
		// jLabel14.setBounds(255,116,100,22);

		this.bottom.setModel(new CustomSpinnerModel());
		// bottom.setBounds(300,116,65,22);
		gbc.gridx = 4;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.bottom.setMinimumSize(new Dimension(65, 22));
		this.bottom.setPreferredSize(new Dimension(65, 22));
		this.printerPanel.add(this.bottom, gbc);

		ChangeListener marginListener = new ChangeListener() {
			static final double mmToSubInch = 72 / 25.4;

			@Override
			public void stateChanged(ChangeEvent e) {
				MarginPaper paper = getSelectedPaper();
				if (paper == null) return;

				double l = (Double) PrintPanel.this.left.getValue() * mmToSubInch;
				double r = (Double) PrintPanel.this.right.getValue() * mmToSubInch;
				double t = (Double) PrintPanel.this.top.getValue() * mmToSubInch;
				double b = (Double) PrintPanel.this.bottom.getValue() * mmToSubInch;
				paper.setImageableArea(l, t, (paper.getWidth() - l) - r, (paper.getHeight() - t) - b);
				updatePreview();
			}
		};
		this.left.addChangeListener(marginListener);
		this.right.addChangeListener(marginListener);
		this.top.addChangeListener(marginListener);
		this.bottom.addChangeListener(marginListener);

		this.jLabel15.setText(Messages.getMessage("PdfViewerPrintResolution.text"));
		gbc.gridx = 0;
		gbc.gridy = 4;
		gbc.gridwidth = 1;
		this.printerPanel.add(this.jLabel15, gbc);
		// jLabel15.setBounds(10, 153, 80, 22);

		gbc.gridx = 1;
		gbc.gridy = 4;
		gbc.gridwidth = 5;
		this.printerPanel.add(this.resolution, gbc);
		// resolution.setBounds(90, 153, 290, 22);

		this.tabbedPane.addTab(Messages.getMessage("PdfViewerPrintTab.printer"), this.printerPanel);
		// add(printerPanel);
		// printerPanel.setBounds(10, 7, 520, 158);
		/**
		 * END Printer PANEL
		 */

		/**
		 * START Print Range PANEL
		 */
		this.printRangePanel.setLayout(new GridBagLayout());

		// printRangePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null,
		// Messages.getMessage("PdfViewerLabel.PrintRange"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
		// javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font(
		// "Tahoma", 0, 11), new java.awt.Color(0, 0, 255)));

		this.pagesFrom.setText("1");
		this.pagesFrom.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mousePressed(java.awt.event.MouseEvent evt) {
				pagesBoxPressed(evt);
			}
		});

		gbc.gridx = 1;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.pagesFrom.setMinimumSize(new Dimension(65, 22));
		this.pagesFrom.setPreferredSize(new Dimension(65, 22));
		gbc.insets = new Insets(0, 0, 0, 0);
		this.printRangePanel.add(this.pagesFrom, gbc);
		gbc.insets = new Insets(5, 5, 5, 5);

		this.buttonGroup1.add(this.printRangeCurrentPage);
		this.printRangeCurrentPage.setText(Messages.getMessage("PdfViewerRadioButton.CurrentPage"));
		this.printRangeCurrentPage.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.printRangeCurrentPage.setMargin(new java.awt.Insets(0, 0, 0, 0));
		this.printRangeCurrentPage.setOpaque(false);
		this.printRangeCurrentPage.addItemListener(new java.awt.event.ItemListener() {
			@Override
			public void itemStateChanged(java.awt.event.ItemEvent evt) {
				currentPageStateChanged(evt);
			}
		});

		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.printRangePanel.add(this.printRangeCurrentPage, gbc);
		// printRangeCurrentPage.setBounds(20, 64, 120, 15);

		this.buttonGroup1.add(this.printRangeAll);
		this.printRangeAll.setSelected(true);
		this.printRangeAll.setText(Messages.getMessage("PdfViewerRadioButton.All"));
		this.printRangeAll.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.printRangeAll.setMargin(new java.awt.Insets(0, 0, 0, 0));
		this.printRangeAll.setOpaque(false);

		if (this.isFirstTime) {
			this.printRangeAll.addItemListener(new java.awt.event.ItemListener() {
				@Override
				public void itemStateChanged(java.awt.event.ItemEvent evt) {
					allStateChanged(evt);
				}
			});
		}

		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		this.printRangePanel.add(this.printRangeAll, gbc);
		// printRangeAll.setBounds(20, 20, 70, 15);

		this.buttonGroup1.add(this.printRangeCurrentView);
		this.printRangeCurrentView.setText(Messages.getMessage("PdfViewerPrint.CurrentView"));
		this.printRangeCurrentView.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.printRangeCurrentView.setEnabled(true);
		this.printRangeCurrentView.setMargin(new java.awt.Insets(0, 0, 0, 0));
		this.printRangeCurrentView.setOpaque(false);
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		this.printRangePanel.add(this.printRangeCurrentView, gbc);
		// printRangeCurrentView.setBounds(20, 42, 140, 15);

		// Disable in non single mode
		if (this.pdf.getDisplayView() != Display.SINGLE_PAGE) {
			this.printRangeCurrentView.setEnabled(false);
			this.printRangeCurrentView.setToolTipText(Messages.getMessage("PageLayoutMessage.SinglePageOnly"));
		}
		else {
			this.printRangeCurrentView.setEnabled(true);
			this.printRangeCurrentView.setToolTipText(null);
		}

		if (this.isFirstTime) {
			this.printRangeCurrentView.addItemListener(new java.awt.event.ItemListener() {
				@Override
				public void itemStateChanged(java.awt.event.ItemEvent evt) {
					printRangeCurrentView(evt);

				}
			});
		}

		this.buttonGroup1.add(this.printRangeFrom);
		this.printRangeFrom.setText(Messages.getMessage("PdfViewerPrint.PagesFrom"));
		this.printRangeFrom.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.printRangeFrom.setMargin(new java.awt.Insets(0, 0, 0, 0));
		this.printRangeFrom.setOpaque(false);

		if (this.isFirstTime) {
			this.printRangeFrom.addItemListener(new java.awt.event.ItemListener() {
				@Override
				public void itemStateChanged(java.awt.event.ItemEvent evt) {
					pagesFromStateChanged(evt);
				}
			});
		}

		gbc.gridx = 0;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.printRangePanel.add(this.printRangeFrom, gbc);
		// printRangeFrom.setBounds(20, 86, 140, 15);

		this.jLabel4.setText(Messages.getMessage("PdfViewerPrint.Subset"));
		gbc.gridx = 0;
		gbc.gridy = 4;
		gbc.gridwidth = 1;
		this.printRangePanel.add(this.jLabel4, gbc);
		// jLabel4.setBounds(10, 125, 100, 14);

		this.printRangeSubset.setModel(new javax.swing.DefaultComboBoxModel(new String[] { Messages.getMessage("PdfViewerPrint.AllPagesInRange"),
				Messages.getMessage("PdfViewerPrint.OddPagesOnly"), Messages.getMessage("PdfViewerPrint.EvenPagesOnly") }));
		gbc.gridx = 1;
		gbc.gridy = 4;
		gbc.gridwidth = 4;
		gbc.insets = new Insets(5, 0, 5, 0);
		this.printRangePanel.add(this.printRangeSubset, gbc);
		gbc.insets = new Insets(5, 5, 5, 5);
		// printRangeSubset.setBounds(90, 122, 290, 22);
		this.printRangeSubset.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
			}
		});

		this.printRangeReversePages.setText(Messages.getMessage("PdfViewerPrint.ReversePages"));
		this.printRangeReversePages.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.printRangeReversePages.setMargin(new java.awt.Insets(0, 0, 0, 0));
		gbc.gridx = 0;
		gbc.gridy = 5;
		gbc.gridwidth = 3;
		this.printRangePanel.add(this.printRangeReversePages, gbc);
		// printRangeReversePages.setBounds(20, 160, 120, 15);
		this.printRangeReversePages.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
			}
		});

		this.jLabel7.setText(Messages.getMessage("PdfViewerPrint.PagesTo"));
		gbc.gridx = 2;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.printRangePanel.add(this.jLabel7, gbc);
		// jLabel7.setBounds(190, 86, 30, 14);

		this.pagesTo.setText(String.valueOf(this.pageCount));

		if (this.isFirstTime) {
			this.pagesTo.addMouseListener(new java.awt.event.MouseAdapter() {
				@Override
				public void mousePressed(java.awt.event.MouseEvent evt) {
					pagesBoxPressed(evt);
				}
			});
		}
		gbc.gridx = 3;
		gbc.gridy = 3;
		gbc.gridwidth = 1;
		this.pagesTo.setMinimumSize(new Dimension(65, 22));
		this.pagesTo.setPreferredSize(new Dimension(65, 22));
		gbc.insets = new Insets(0, 0, 0, 0);
		this.printRangePanel.add(this.pagesTo, gbc);
		gbc.insets = new Insets(5, 5, 5, 5);

		this.tabbedPane.addTab(Messages.getMessage("PdfViewerPrintTab.range"), this.printRangePanel);
		// add(printRangePanel);
		// printRangePanel.setBounds(10, 140, 320, 160);
		/**
		 * END Print Range PANEL
		 */

		/**
		 * START Page Handling PANEL
		 */
		this.pageHandlingPanel.setLayout(new GridBagLayout());

		// pageHandlingPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null,
		// Messages.getMessage("PdfViewerLabel.PageHandling"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
		// javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 11),
		// new java.awt.Color(0, 0, 255)));

		this.jLabel8.setText(Messages.getMessage("PdfViewerPrint.Copies"));
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		this.pageHandlingPanel.add(this.jLabel8, gbc);
		// jLabel8.setBounds(10, 20, 50, 14);

		this.printHandlingCopies.setModel(new SpinnerNumberModel(1, 1, 1000, 1));
		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.fill = GridBagConstraints.VERTICAL;
		gbc.insets = new Insets(0, 0, 0, 0);
		gbc.anchor = GridBagConstraints.WEST;
		this.printHandlingCopies.setMinimumSize(new Dimension(65, 22));
		this.printHandlingCopies.setPreferredSize(new Dimension(65, 22));
		this.pageHandlingPanel.add(this.printHandlingCopies, gbc);
		// printHandlingCopies.setBounds(90, 17, 60, 20);
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.insets = new Insets(5, 5, 5, 5);

		this.jLabel9.setText(Messages.getMessage("PdfViewerPrint.PageScaling"));
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		this.pageHandlingPanel.add(this.jLabel9, gbc);
		// jLabel9.setBounds(10, 50, 120, 14);

		this.printHandlingScaling.setModel(new javax.swing.DefaultComboBoxModel(PrinterOptions.PRINT_SCALING_OPTIONS));
		this.printHandlingScaling.setSelectedIndex(PrinterOptions.LAST_SCALING_CHOICE);
		gbc.gridx = 1;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		gbc.insets = new Insets(5, 0, 5, 0);
		this.pageHandlingPanel.add(this.printHandlingScaling, gbc);
		gbc.insets = new Insets(5, 5, 5, 5);
		// printHandlingScaling.setBounds(90, 47, 290, 22);
		this.printHandlingScaling.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
			}
		});

		this.autoRotateCenter.setSelected(true);
		this.autoRotateCenter.setText((Messages.getMessage("PdfViewerPrint.AutoRotateAndCenter")));
		this.autoRotateCenter.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.autoRotateCenter.setMargin(new java.awt.Insets(0, 0, 0, 0));
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		this.pageHandlingPanel.add(this.autoRotateCenter, gbc);
		// autoRotateCenter.setBounds(20, 88, 260, 15);
		this.autoRotateCenter.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
			}
		});

		this.paperSourceByPDF.setText(Messages.getMessage("PdfViewerPrint.ChoosePaperByPdfSize"));
		this.paperSourceByPDF.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		this.paperSourceByPDF.setMargin(new java.awt.Insets(0, 0, 0, 0));
		gbc.gridx = 0;
		gbc.gridy = 3;
		gbc.gridwidth = 2;
		this.pageHandlingPanel.add(this.paperSourceByPDF, gbc);
		// paperSourceByPDF.setBounds(20, 112, 300, 15);
		this.paperSourceByPDF.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
			}
		});

		this.grayscale.setText(Messages.getMessage("PdfViewerPrint.Grayscale"));
		this.grayscale.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		gbc.gridx = 0;
		gbc.gridy = 4;
		gbc.gridwidth = 2;
		this.pageHandlingPanel.add(this.grayscale, gbc);
		this.grayscale.setMargin(new java.awt.Insets(0, 0, 0, 0));
		// grayscale.setBounds(20,137,300,15);
		this.grayscale.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				updatePreview();
			}
		});

		this.tabbedPane.addTab(Messages.getMessage("PdfViewerPrintTab.handling"), this.pageHandlingPanel);
		// add(pageHandlingPanel);
		// pageHandlingPanel.setBounds(10, 300, 320, 170);
		/**
		 * END Page Handling PANEL
		 */

		/**
		 * START Preview PANEL
		 */
		this.previewPanel.setLayout(null);

		this.previewPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getMessage("PdfViewerLabel.PrintPreview"),
				javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma",
						0, 11), Color.BLACK));

		this.previewPanel.add(this.previewComponent);
		this.previewComponent.setBounds(5, 5, 220, 275);

		this.previewPanel.add(this.previewSlider);
		this.previewSlider.setBounds(5, 280, 220, 40);
		this.previewSlider.setValue(1);
		updatePreview();

		add(this.previewPanel);
		this.previewPanel.setBounds(420, 7, 230, 330);
		/**
		 * END Preview PANEL
		 */

		// printToFile.setText(Messages.getMessage("PdfViewerPrint.PrintToFile"));
		// printToFile.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
		// printToFile.setMargin(new java.awt.Insets(0, 0, 0, 0));
		// add(printToFile);
		// printToFile.setBounds(20, 485, 160, 15);
		// printToFile.setEnabled(false);

		this.okButton.setText(Messages.getMessage("PdfMessage.Ok"));

		if (this.isFirstTime) {
			this.okButton.addActionListener(new java.awt.event.ActionListener() {
				@Override
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					okEvent(evt);
				}
			});
		}

		add(this.okButton);
		this.okButton.setBounds(445, 348, 90, 23);

		this.cancelButton.setText(Messages.getMessage("PdfMessage.Cancel"));

		if (this.isFirstTime) {
			this.cancelButton.addActionListener(new java.awt.event.ActionListener() {
				@Override
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					cancelEvent(evt);
				}
			});
		}

		add(this.cancelButton);
		this.cancelButton.setBounds(560, 348, 90, 23);
	}// </editor-fold>

	private static String[] getAvailableResolutions(PrintService p) {
		PrinterResolution[] resolutions = (PrinterResolution[]) p.getSupportedAttributeValues(PrinterResolution.class,
				DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);

		if (resolutions == null) return new String[] { "Default" };

		String[] names = new String[resolutions.length];
		for (int i = 0; i < resolutions.length; i++) {
			PrinterResolution res = resolutions[i];
			names[i] = res.getCrossFeedResolution(ResolutionSyntax.DPI) + "x" + res.getFeedResolution(ResolutionSyntax.DPI) + " dpi";
		}

		return names;
	}

	public PrinterResolution getResolution() {
		PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
		PrintService p = null;
		for (PrintService p1 : ps) {
			if (p1.getName().equals(this.printerName.getSelectedItem())) p = p1;
		}

		PrinterResolution[] resolutions = ((PrinterResolution[]) p.getSupportedAttributeValues(PrinterResolution.class,
				DocFlavor.SERVICE_FORMATTED.PAGEABLE, null));

		if (resolutions == null) return null;

		return resolutions[this.resolution.getSelectedIndex()];
	}

	private int getDefaultResolutionIndex() {
		// get print service
		PrintService[] ps = PrintServiceLookup.lookupPrintServices(null, null);
		PrintService p = null;
		for (PrintService p1 : ps) {
			if (p1.getName().equals(this.printerName.getSelectedItem())) p = p1;
		}

		// get available resolutions
		PrinterResolution[] resolutions = (PrinterResolution[]) p.getSupportedAttributeValues(PrinterResolution.class,
				DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);

		if (resolutions == null) return 0;

		if (this.defaultResolution == -1) this.defaultResolution = 600;

		// find nearest resolution
		int minDiff = Integer.MAX_VALUE;
		int indexToUse = 0;
		for (int i = 0; i < resolutions.length; i++) {
			PrinterResolution res = resolutions[i];
			int cfDiff = res.getCrossFeedResolution(ResolutionSyntax.DPI) - this.defaultResolution;
			if (cfDiff < 0) cfDiff = -cfDiff;
			int fDiff = res.getFeedResolution(ResolutionSyntax.DPI) - this.defaultResolution;
			if (fDiff < 0) fDiff = -fDiff;

			if (cfDiff + fDiff < minDiff) {
				minDiff = cfDiff + fDiff;
				indexToUse = i;
			}
		}

		return indexToUse;
	}

	private void updateMargins() {

		MarginPaper p = getSelectedPaper();

		if (p == null) return;

		// Update minimum values
		((CustomSpinnerModel) this.left.getModel()).setMinValue(p.getMinX() * mmPerSubInch);
		((CustomSpinnerModel) this.top.getModel()).setMinValue(p.getMinY() * mmPerSubInch);
		((CustomSpinnerModel) this.right.getModel()).setMinValue((p.getWidth() - p.getMaxRX()) * mmPerSubInch);
		((CustomSpinnerModel) this.bottom.getModel()).setMinValue((p.getHeight() - p.getMaxBY()) * mmPerSubInch);

		// Set values to min
		Double a = (double) 0;
		this.left.setValue(a);
		this.top.setValue(a);
		this.right.setValue(a);
		this.bottom.setValue(a);
	}

	private void printPreview(Graphics2D g2) {
		int w = this.previewComponent.getWidth();
		int h = this.previewComponent.getHeight();
		int pW, pH, iW, iH, iX, iY; // values in 72ths of an inch
		int pageWidth, pageHeight;

		// In print current view use the visible area of the screen instead of the page heights
		if (this.printRangeCurrentView.isSelected()) {
			pageWidth = (int) (this.pdf.getVisibleRect().getWidth() / (this.pdf.getScaling()));
			pageHeight = (int) (this.pdf.getVisibleRect().getHeight() / (this.pdf.getScaling()));
		}
		else {
			pageWidth = this.pdf.getPdfPageData().getCropBoxWidth(this.currentPreviewedPage);
			pageHeight = this.pdf.getPdfPageData().getCropBoxHeight(this.currentPreviewedPage);
		}

		// set paper size and printable area
		if (this.paperSourceByPDF.isSelected()) {
			pW = pageWidth; // Paper width
			pH = pageHeight; // Paper height
			iW = pW; // Imageable area width
			iH = pH; // Imageable area height
			iX = 0; // Imageable area start x
			iY = 0; // Imageable area start y
		}
		else {
			MarginPaper p = this.paperDefinitions.getSelectedPaper(this.pageSize.getSelectedItem());
			if (p == null) {
				g2.drawString(Messages.getMessage("PdfPrintPreview.Loading"), (w / 2) - 25, (h / 2) - 5);
				return;
			}
			pW = (int) p.getWidth();
			pH = (int) p.getHeight();
			iX = (int) p.getImageableX();
			iY = (int) p.getImageableY();
			iW = (int) p.getImageableWidth();
			iH = (int) p.getImageableHeight();
		}

		// check auto rotate
		if (this.autoRotateCenter.isSelected() && ((pageWidth > pageHeight && iW < iH) || (pageWidth < pageHeight && iW > iH))) {
			int temp;
			temp = pW;
			pW = pH;
			pH = temp;

			temp = iW;
			iW = iH;
			iH = temp;
			temp = iX;
			iX = iY;
			iY = temp;

			// flip
			iY = pH - iY - iH;
		}

		// Set offsets
		int lO = 25;
		int tO = 30;
		int rO = 5;
		int bO = 25;

		double paperHeightInInches = pH / 72d;
		double paperWidthInInches = pW / 72d;

		// Calculate scaling
		double wScale = (double) (w - (lO + rO)) / pW;
		double hScale = (double) (h - (tO + bO)) / pH;
		double scale;
		if (wScale < hScale) scale = wScale;
		else scale = hScale;

		// Scale all values
		pW = (int) (scale * pW);
		pH = (int) (scale * pH);
		iX = (int) (scale * iX);
		iY = (int) (scale * iY);
		iW = (int) (scale * iW);
		iH = (int) (scale * iH);
		pageWidth = (int) (scale * pageWidth);
		pageHeight = (int) (scale * pageHeight);

		double pageScale = 1;
		if (this.printHandlingScaling.getSelectedIndex() == 1 || // Fit
				(this.printHandlingScaling.getSelectedIndex() == 2 && (pageWidth > iW || pageHeight > iH))) { // Reduce
			pageScale = (double) iW / pageWidth;
			if (((double) iH / pageHeight) < pageScale) pageScale = (double) iH / pageHeight;

			pageWidth = (int) (pageScale * pageWidth);
			pageHeight = (int) (pageScale * pageHeight);
		}

		// Include any centering
		lO += (w - (lO + rO + pW)) / 2;
		tO += (h - (tO + bO + pH)) / 2;

		// Fill page background
		g2.setPaint(Color.WHITE);
		g2.fillRect(lO, tO, pW, pH);

		// Draw printable area
		g2.setPaint(Color.RED);
		g2.drawLine(lO + iX, tO, lO + iX, tO + pH);
		g2.drawLine(lO, tO + iY, lO + pW, tO + iY);
		g2.drawLine(lO + iW + iX, tO, lO + iW + iX, tO + pH);
		g2.drawLine(lO, tO + iH + iY, lO + pW, tO + iH + iY);

		// fudge printable area for image drawing
		iX++;
		iY++;
		iW--;
		iH--;

		g2.setPaint(Color.BLACK);

		// Draw width bar
		NumberFormat f = NumberFormat.getNumberInstance();
		f.setMaximumFractionDigits(1);
		String widthString = f.format(paperWidthInInches);
		int tLen = widthString.length() * 3;

		g2.drawString(widthString, lO + (pW / 2) - tLen, tO - 5);
		g2.drawLine(lO, tO - 15, lO, tO - 5);
		g2.drawLine(lO + pW, tO - 15, lO + pW, tO - 5);
		g2.drawLine(lO, tO - 10, (lO + (pW / 2) - tLen) - 6, tO - 10);
		g2.drawLine((lO + (pW / 2) + tLen) + 6, tO - 10, lO + pW, tO - 10);
		g2.drawLine(lO, tO - 10, lO + 5, tO - 15);
		g2.drawLine(lO, tO - 10, lO + 5, tO - 5);
		g2.drawLine(lO + pW, tO - 10, lO + pW - 5, tO - 15);
		g2.drawLine(lO + pW, tO - 10, lO + pW - 5, tO - 5);

		// Draw height bar
		String heightString = f.format(paperHeightInInches);
		tLen = heightString.length() * 3;
		g2.drawString(heightString, (lO - 12) - tLen, tO + (pH / 2) + 5);
		g2.drawLine(lO - 15, tO, lO - 5, tO);
		g2.drawLine(lO - 15, tO + pH, lO - 5, tO + pH);
		g2.drawLine(lO - 10, tO, lO - 10, (tO + (pH / 2)) - 8);
		g2.drawLine(lO - 10, ((tO + (pH / 2)) + 8), lO - 10, tO + pH);
		g2.drawLine(lO - 10, tO, lO - 5, tO + 5);
		g2.drawLine(lO - 10, tO, lO - 15, tO + 5);
		g2.drawLine(lO - 10, tO + pH, lO - 15, tO + pH - 5);
		g2.drawLine(lO - 10, tO + pH, lO - 5, tO + pH - 5);

		// draw page
		try {
			BufferedImage img;

			// print current view uses current display on PdfDecoder
			if (this.printRangeCurrentView.isSelected()) {
				img = new BufferedImage((int) this.pdf.getVisibleRect().getWidth(), (int) this.pdf.getVisibleRect().getHeight(),
						BufferedImage.TYPE_INT_ARGB);
				Graphics g = img.getGraphics();
				g.translate((int) -this.pdf.getVisibleRect().getX(), (int) -this.pdf.getVisibleRect().getY());

				// store border and background and restore after paint
				Border bStore = this.pdf.getBorder();
				Color cStore = this.pdf.getBackground();
				this.pdf.setBorder(BorderFactory.createEmptyBorder());
				this.pdf.setBackground(Color.WHITE);
				this.pdf.paintComponent(g);
				this.pdf.setBorder(bStore);
				this.pdf.setBackground(cStore);
			}
			else {
				img = this.pdf.getPageAsImage(this.currentPreviewedPage);
			}

			if (this.grayscale.isSelected()) img = ColorSpaceConvertor.convertColorspace(img, BufferedImage.TYPE_BYTE_GRAY);

			g2.setClip(lO + iX, tO + iY, iW, iH);

			int centeringX = (int) ((iW - pageWidth) / 2d);
			int centeringY = (int) ((iH - pageHeight) / 2d);

			g2.drawImage(img, lO + iX + centeringX, tO + iY + centeringY, pageWidth, pageHeight, null);
		}
		catch (PdfException e) {}

		// Draw border
		g2.setClip(null);
		g2.drawRect(lO, tO, pW, pH);

		f.setMaximumFractionDigits(0);
		g2.drawString(Messages.getMessage("PdfPrintPreview.UnitScale") + f.format(pageScale * 100) + '%', 5, h - 5);
	}

	private void updatePreview() {
		int selection = this.previewSlider.getValue();

		// check for illogical settings
		SetOfIntegerSyntax set = getPrintRange();
		if (set == null) {

			// Illogical - preview nothing
			this.currentPreviewedPage = 0;
			this.pagePrintCount = 0;

		}
		else {

			int[][] ranges = set.getMembers();

			// calculate length
			int count = 0;
			for (int[] range1 : ranges) {
				count += range1[1] - (range1[0] - 1);
			}
			int[] pagesToPrint = new int[count];
			this.pagePrintCount = pagesToPrint.length;

			// populate array with page numbers
			count = 0;
			for (int[] range : ranges) {
				int rangeLength = range[1] - (range[0] - 1);
				for (int j = 0; j < rangeLength; j++) {
					pagesToPrint[count] = range[0] + j;
					count++;
				}
			}

			// check selection value
			if (selection > this.pagePrintCount) {
				selection = 1;
				this.previewSlider.setValue(1);
			}

			// Work out which page to preview
			if (this.printRangeReversePages.isSelected()) this.currentPreviewedPage = pagesToPrint[pagesToPrint.length - selection];
			else this.currentPreviewedPage = pagesToPrint[selection - 1];
		}

		// recalculate previewSlider
		this.previewSlider.setMaxValue(this.pagePrintCount);

		// redraw
		this.previewComponent.repaint();
	}

	private void pagesBoxPressed(java.awt.event.MouseEvent evt) {
		this.printRangeFrom.setSelected(true);
		this.printRangeSubset.setEnabled(true);
		this.printRangeReversePages.setEnabled(true);
		updatePreview();
	}

	private void pagesFromStateChanged(java.awt.event.ItemEvent evt) {
		if (this.printRangeFrom.isSelected()) {
			this.printRangeSubset.setEnabled(true);
			this.printRangeReversePages.setEnabled(true);
			updatePreview();
		}
	}

	private void printRangeCurrentView(java.awt.event.ItemEvent evt) {
		if (this.printRangeCurrentView.isSelected()) {
			this.printRangeSubset.setEnabled(false);
			this.printRangeReversePages.setEnabled(false);
			updatePreview();
		}
	}

	private void currentPageStateChanged(java.awt.event.ItemEvent evt) {
		if (this.printRangeCurrentPage.isSelected()) {
			this.printRangeSubset.setEnabled(false);
			this.printRangeReversePages.setEnabled(false);
			updatePreview();
		}
	}

	private void allStateChanged(java.awt.event.ItemEvent evt) {
		if (this.printRangeAll.isSelected()) {
			this.printRangeSubset.setEnabled(true);
			this.printRangeReversePages.setEnabled(true);
			updatePreview();
		}
	}

	private void cancelEvent(java.awt.event.ActionEvent evt) {
		this.okClicked = false;
		getTopLevelAncestor().setVisible(false);
	}

	private void okEvent(java.awt.event.ActionEvent evt) {
		this.okClicked = true;
		getTopLevelAncestor().setVisible(false);
	}

	// Variables declaration - do not modify
	private javax.swing.JCheckBox autoRotateCenter;
	private javax.swing.ButtonGroup buttonGroup1;
	private javax.swing.JButton cancelButton;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JLabel jLabel2;
	private javax.swing.JLabel jLabel4;
	private javax.swing.JLabel jLabel7;
	private javax.swing.JLabel jLabel8;
	private javax.swing.JLabel jLabel9;
	private javax.swing.JLabel jLabel10;
	private javax.swing.JLabel jLabel11;
	private javax.swing.JLabel jLabel12;
	private javax.swing.JLabel jLabel13;
	private javax.swing.JLabel jLabel14;
	private javax.swing.JLabel jLabel15;
	private javax.swing.JSpinner left;
	private javax.swing.JSpinner right;
	private javax.swing.JSpinner top;
	private javax.swing.JSpinner bottom;
	private javax.swing.JComboBox resolution;
	private javax.swing.JButton okButton;
	private javax.swing.JPanel pageHandlingPanel;
	private javax.swing.JPanel previewPanel;
	private javax.swing.JComponent previewComponent;
	private CustomSlider previewSlider;
	private javax.swing.JComboBox pageSize;
	private javax.swing.JTextField pagesFrom;
	private javax.swing.JTextField pagesTo;
	private javax.swing.JCheckBox paperSourceByPDF;
	private javax.swing.JCheckBox grayscale;
	private javax.swing.JSpinner printHandlingCopies;
	private javax.swing.JComboBox printHandlingScaling;
	private javax.swing.JRadioButton printRangeAll;
	private javax.swing.JRadioButton printRangeCurrentPage;
	private javax.swing.JRadioButton printRangeCurrentView;
	private javax.swing.JRadioButton printRangeFrom;
	private javax.swing.JPanel printRangePanel;
	private javax.swing.JCheckBox printRangeReversePages;
	private javax.swing.JComboBox printRangeSubset;
	// private javax.swing.JCheckBox printToFile;
	private javax.swing.JComboBox printerName;
	private javax.swing.JPanel printerPanel;
	private javax.swing.JTabbedPane tabbedPane;

	// End of variables declaration

	/**
	 * return range as SetOfIntegerSytax - if you try to do something silly like print all even pages in rage 1-1 you will get null returned
	 */
	public SetOfIntegerSyntax getPrintRange() {

		SetOfIntegerSyntax pageRange = null;

		if (this.printRangeAll.isSelected()) {

			pageRange = new PageRanges(1, this.pageCount);

			if (this.printRangeSubset.getSelectedIndex() == 0) return pageRange;

			if (this.printRangeSubset.getSelectedIndex() == 1) {
				String members = "";
				int i = -1;
				while ((i = pageRange.next(i)) != -1) {
					if (i % 2 == 1) {
						members += i + ",";
					}
				}

				StringBuilder sb = new StringBuilder(members);
				sb.deleteCharAt(members.length() - 1);
				members = sb.toString();

				pageRange = new PageRanges(members);
			}
			else
				if (this.printRangeSubset.getSelectedIndex() == 2) {
					String members = "";
					int i = -1;
					while ((i = pageRange.next(i)) != -1) {
						if (i % 2 == 0) {
							members += i + ",";
						}
					}

					StringBuilder sb = new StringBuilder(members);
					sb.deleteCharAt(members.length() - 1);
					members = sb.toString();

					pageRange = new PageRanges(members);
				}

		}
		else
			if (this.printRangeCurrentPage.isSelected()) {

				pageRange = new PageRanges(this.currentPage);

			}
			else
				if (this.printRangeCurrentView.isSelected()) {

					pageRange = new PageRanges(this.currentPage);

				}
				else
					if (this.printRangeFrom.isSelected()) {

						int start, end;
						try {
							start = Integer.parseInt(this.pagesFrom.getText());
						}
						catch (NumberFormatException e) {
							this.pagesFrom.setText("" + 1);
							start = 1;
						}
						try {
							end = Integer.parseInt(this.pagesTo.getText());
						}
						catch (NumberFormatException e) {
							this.pagesTo.setText(String.valueOf(this.pageCount));
							end = this.pageCount;
						}

						// Check values in range
						if (start < 0) {
							start = 1;
							this.pagesFrom.setText("" + 1);
						}
						else
							if (start > this.pageCount) {
								start = this.pageCount;
								this.pagesFrom.setText(String.valueOf(this.pageCount));
							}
						if (end < 0) {
							end = 1;
							this.pagesTo.setText("" + 1);
						}
						else
							if (end > this.pageCount) {
								end = this.pageCount;
								this.pagesTo.setText(String.valueOf(this.pageCount));
							}

						if (start > end) {
							int tmp = end;
							end = start;
							start = tmp;

							if (Viewer.showMessages) JOptionPane.showMessageDialog(this, Messages.getMessage("PdfViewerPrint.SwapValues"));
						}
						pageRange = new PageRanges(start, end);

						if (this.printRangeSubset.getSelectedIndex() == 0) return pageRange;

						if (this.printRangeSubset.getSelectedIndex() == 1) {
							String members = "";
							int i = -1;
							while ((i = pageRange.next(i)) != -1) {
								if (i % 2 == 1) {
									members += i + ",";
								}
							}

							StringBuilder sb = new StringBuilder(members);
							if (members.length() == 0) return null;

							sb.deleteCharAt(members.length() - 1);
							members = sb.toString();

							pageRange = new PageRanges(members);
						}
						else
							if (this.printRangeSubset.getSelectedIndex() == 2) {
								String members = "";
								int i = -1;
								while ((i = pageRange.next(i)) != -1) {
									if (i % 2 == 0) {
										members += i + ",";
									}
								}

								StringBuilder sb = new StringBuilder(members);
								int length = members.length();
								if (length > 0) sb.deleteCharAt(length - 1);
								members = sb.toString();

								if (members.length() > 0) pageRange = new PageRanges(members);
								else pageRange = null;
							}
					}

		return pageRange;
	}

	public int getCopies() {
		String copies = this.printHandlingCopies.getValue().toString();
		return Integer.parseInt(copies);
	}

	/**
	 * return setting for type of scaling to use PAGE_SCALING_NONE,PAGE_SCALING_FIT_TO_PRINTER_MARGINS,PAGE_SCALING_REDUCE_TO_PRINTER_MARGINS see
	 * org.jpedal.objects.contstants.PrinterOptions for all values
	 */
	public int getPageScaling() {

		int option = this.printHandlingScaling.getSelectedIndex();

		int value = 0;
		// make choice
		switch (option) {
			case 0: // No scaling
				value = PrinterOptions.PAGE_SCALING_NONE;
				break;

			case 1: // Fit to scaling
				value = PrinterOptions.PAGE_SCALING_FIT_TO_PRINTER_MARGINS;
				break;

			case 2: // Reduce to scaling
				value = PrinterOptions.PAGE_SCALING_REDUCE_TO_PRINTER_MARGINS;
				break;

		}

		// remember last option for next print dialog
		PrinterOptions.LAST_SCALING_CHOICE = value;

		return value;
	}

	public String getPrinter() {

		if (this.printerName == null) return "";
		else {

			if (this.printerName.getSelectedItem() == null) return null;
			else return this.printerName.getSelectedItem().toString();
		}
	}

	public boolean okClicked() {
		return this.okClicked;
	}

	public boolean isAutoRotateAndCenter() {
		return this.autoRotateCenter.isSelected();
	}

	public boolean isPaperSourceByPDFSize() {
		return this.paperSourceByPDF.isSelected();
	}

	public boolean isPrintingCurrentView() {
		return this.printRangeCurrentView.isSelected();
	}

	public String[] getAvailablePaperSizes() {
		return this.paperDefinitions.getAvailablePaperSizes();
	}

	/** return selected Paper */
	public MarginPaper getSelectedPaper() {
		return this.paperDefinitions.getSelectedPaper(this.pageSize.getSelectedItem());
	}

	public boolean isPagesReversed() {
		return this.printRangeReversePages.isSelected();
	}

	public boolean isOddPagesOnly() {
		return this.printRangeSubset.getSelectedIndex() == 1;
	}

	public boolean isEvenPagesOnly() {
		return this.printRangeSubset.getSelectedIndex() == 2;
	}

	public boolean isMonochrome() {
		return this.grayscale.isSelected();
	}

	private class CustomSlider extends JPanel {

		private static final long serialVersionUID = -3375046146423776311L;
		private int value = 1, maxValue = 100;
		private static final int rightMargin = 9;
		private static final int leftMargin = 9;
		private boolean dragging = false;

		public CustomSlider() {
			addMouseMotionListener(new MouseMotionAdapter() {
				@Override
				public void mouseDragged(MouseEvent e) {
					if (CustomSlider.this.dragging) {
						CustomSlider.this.value = (int) ((((double) (e.getX() - leftMargin) / (getWidth() - (leftMargin + rightMargin))) * (CustomSlider.this.maxValue - 1)) + 1.5);
						if (CustomSlider.this.value > CustomSlider.this.maxValue) CustomSlider.this.value = CustomSlider.this.maxValue;
						if (CustomSlider.this.value < 1) CustomSlider.this.value = 1;
						updatePreview();
						repaint();
					}
				}
			});
			addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					if (e.getY() < 20) {
						double newValue = (((double) (e.getX() - leftMargin) / (getWidth() - (leftMargin + rightMargin))) * (CustomSlider.this.maxValue - 1)) + 1;
						if (newValue > CustomSlider.this.value) CustomSlider.this.value++;
						else
							if (newValue < CustomSlider.this.value) CustomSlider.this.value--;

						if (CustomSlider.this.value > CustomSlider.this.maxValue) CustomSlider.this.value = CustomSlider.this.maxValue;
						if (CustomSlider.this.value < 1) CustomSlider.this.value = 1;
						updatePreview();
						repaint();
					}
				}

				@Override
				public void mousePressed(MouseEvent e) {
					if (e.getY() < 20) CustomSlider.this.dragging = true;
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					CustomSlider.this.dragging = false;
				}
			});
		}

		@Override
		public void paint(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

			final int w = this.getWidth();
			final int h = this.getHeight();

			// fill background
			g2.setPaint(new Color(240, 240, 240));
			g2.fillRect(0, 0, w, h);

			// draw text
			g2.setPaint(Color.BLACK);
			g2.drawString(Messages.getMessage("PdfPrintPreview.Sheet") + this.value + Messages.getMessage("PdfPrintPreview.SheetOf") + this.maxValue,
					2, h - 3);

			// draw line
			g2.setPaint(Color.LIGHT_GRAY);
			g2.fillRect(leftMargin + 1, 11, w - ((leftMargin + rightMargin) + 1), 3);
			g2.setPaint(Color.GRAY);
			g2.drawLine(leftMargin, 12, w - rightMargin, 12);

			// draw knob
			float pageX = leftMargin + (((float) (this.value - 1) / (this.maxValue - 1)) * (w - (leftMargin + rightMargin)));
			Shape number = new Ellipse2D.Float(pageX - 6, 6.5f, 12, 12);
			Shape number2 = new Ellipse2D.Float(pageX - 4, 8.5f, 8, 8);
			g2.setPaint(Color.BLACK);
			g2.fill(number);
			g2.setPaint(Color.WHITE);
			g2.fill(number2);
		}

		public void setValue(int value) {
			this.value = value;
			repaint();
		}

		public void setMaxValue(int maxValue) {
			if (maxValue != this.maxValue) {
				this.value = 1;
				this.maxValue = maxValue;
				updatePreview();
				return;
			}
			this.maxValue = maxValue;
			repaint();
		}

		public int getValue() {
			return this.value;
		}
	}

	private static class CustomSpinnerModel extends SpinnerNumberModel {

		private static final long serialVersionUID = -1561911354444155587L;
		private double value = 0;
		private ArrayList<ChangeListener> listeners = new ArrayList<ChangeListener>();
		private double minValue = 0;

		@Override
		public Object getPreviousValue() {
			if (this.value <= this.minValue) return null;
			if (this.value - 0.5 < this.minValue) return this.minValue;
			return this.value - 0.5;
		}

		@Override
		public Object getNextValue() {
			return this.value + 0.5;
		}

		@Override
		public Object getValue() {
			return this.value;
		}

		@Override
		public void addChangeListener(ChangeListener l) {
			this.listeners.add(l);
		}

		@Override
		public void removeChangeListener(ChangeListener l) {
			this.listeners.remove(l);
		}

		@Override
		public void setValue(Object value) {
			try {
				double newValue = (Double) value;
				if (newValue < this.minValue) this.value = this.minValue;
				else this.value = newValue;
			}
			catch (Exception e) {
				throw new IllegalArgumentException();
			}
			ChangeEvent e = new ChangeEvent(this);
			for (Object listener : this.listeners) {
				((ChangeListener) listener).stateChanged(e);
			}
		}

		public void setMinValue(double minValue) {
			this.minValue = minValue;
			setValue(getValue());
		}
	}
}
